package com.rock.minibatis.executor;

import com.rock.minibatis.config.Configuration;
import com.rock.minibatis.config.JdbcProperties;
import com.rock.minibatis.mapping.MappedStatement;

import java.lang.reflect.Field;
import java.lang.reflect.Type;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;

/**
 * 数据库进行操作
 */
public class SimpleExecutor implements  Executor{

    //protected Configuration configuration;
    protected JdbcProperties jdbcConf;

    public SimpleExecutor(Configuration configuration){
        //this.configuration = configuration;
        this.jdbcConf = configuration.getJdbcProperties();
    }

    protected Connection getConnection(){
        Connection connection = null;
        try {
            Class.forName(jdbcConf.getDriver());
            //2、获取数据库连接
            connection = DriverManager.getConnection(jdbcConf.getUrl(), jdbcConf.getUsername(), jdbcConf.getPassword());
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }finally{
            return connection;
        }
    }

    protected void closeStatement(Statement statement) {
        if (statement != null) {
            try {
                statement.close();
            } catch (SQLException var3) {
            }
        }

    }

    public <E> List<E> query(MappedStatement ms, Object parameter) throws SQLException {
        Connection conn = this.getConnection();
        PreparedStatement preparedStatement = conn.prepareStatement(ms.getSql());
        parameterize(preparedStatement, parameter);
        ResultSet rs = preparedStatement.executeQuery();
        List ret = new ArrayList();
        handlerResultSet(rs, ret, ms.getResultType());
        this.closeStatement(preparedStatement);
        return ret;
    }

    private void parameterize(PreparedStatement preparedStatement, Object parameter) throws SQLException {
        if (parameter instanceof String) {
            preparedStatement.setString(1, (String) parameter);
        } else if (parameter instanceof Long) {
            preparedStatement.setLong(1, (Long) parameter);
        } else if (parameter instanceof Integer) {
            preparedStatement.setInt(1, (Integer) parameter);
        }
    }


    //Mybatis源码中会提供专门的ResultSetHandler及默认实现DefaultResultSetHandler
    private <E> void handlerResultSet(ResultSet resultSet, List<E> ret, String className) {
        Class<E> clazz = null;
        try {
            clazz = (Class<E>) Class.forName(className);
            while (resultSet.next()) {
                // 通过反射实例化对象
                Object entity = clazz.newInstance();
                Field[] fields = clazz.getDeclaredFields();
                for (Field field : fields) {
                    field.setAccessible(true);
                    String fname = field.getName();
                    Type type = field.getGenericType();
                    if (type.toString().equals("class java.lang.String")) {
                        String column = resultSet.getString(fname);
                        field.set(entity, column);
                    }else if (type.toString().equals("long")) {
                        Long column = resultSet.getLong(fname);
                        field.set(entity, column);
                    }else if (type.toString().equals("int")) {
                        int column = resultSet.getInt(fname);
                        field.set(entity, column);
                    }
                }
                ret.add((E) entity);
            }
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
    }


}
